//go:build !beanpay
// +build !beanpay

package fas

import (
	"encoding/json"
	"fmt"

	"gitee.com/micro-plat/fas/modules/const/conf"
	"gitee.com/micro-plat/fas/modules/inner/normal"
	"gitee.com/micro-plat/fas/modules/inner/sup"
	"github.com/micro-plat/beanpay/beanpay/account"
	"github.com/micro-plat/beanpay/beanpay/const/ttypes"
	"github.com/micro-plat/lib4go/types"
	"github.com/shopspring/decimal"
)

//DownChannelPay 下游扣款
func DownChannelPay(params *DownPay) (r *DownPayResult, err error) {
	if !conf.KeepAccount {
		return &DownPayResult{Result: "success", Msg: "success"}, nil
	}

	orderAmount, _ := decimal.NewFromFloat(params.DownSellAmount).Sub(decimal.NewFromFloat(params.DownFeeAmount)).Float64()
	data := &normal.DownPay{
		OrderSource:       params.OrderSource,
		DownChannelNo:     params.DownChannelNo,
		TradeOrderNo:      params.TradeOrderNo,
		ExtOrderNo:        params.ExtOrderNo,
		RechargeAccountNo: params.RechargeAccountNo,
		BusinessType:      params.BusinessType,
		CarrierNo:         params.CarrierNo,
		ProvinceNo:        params.ProvinceNo,
		CityNo:            params.CityNo,
		TotalFace:         params.TotalFace,
		RechargeUnit:      params.RechargeUnit,
		OrderTime:         params.OrderTime,
		OrderAmount:       orderAmount,
		ServicePay:        params.DownFeeAmount,
		Memo:              params.Memo,
	}

	billing, err := normal.NewBilling()
	if err != nil {
		return nil, err
	}

	result, err := billing.DownChannelPay(data)
	if err != nil {
		return nil, err
	}

	r = &DownPayResult{}
	err = types.Map2Struct(r, result, "json")
	return
}

//SupDownChannelPay Sup下游扣款
func SupDownChannelPay(params *SupDownPay) (r *DownPayResult, err error) {
	if !conf.KeepAccount {
		return &DownPayResult{Result: "success", Msg: "success"}, nil
	}
	orderAmount, _ := decimal.NewFromFloat(params.DownSellAmount).Sub(decimal.NewFromFloat(params.DownFeeAmount)).Float64()
	data := &sup.DownPay{
		DownChannelNo: params.DownChannelNo,
		TradeOrderNo:  params.TradeOrderNo,
		BusinessType:  params.BusinessType,
		CarrierNo:     params.CarrierNo,
		ProvinceNo:    params.ProvinceNo,
		CityNo:        params.CityNo,
		OrderUnit:     params.OrderUnit,
		OrderFace:     params.OrderFace,
		OrderAmount:   orderAmount,
		OrderTime:     params.OrderTime,
		ChangeTime:    params.ChangeTime,
		Memo:          params.Memo,
	}

	billing, err := sup.NewBilling()
	if err != nil {
		return nil, err
	}

	result, err := billing.DownChannelPay(data)
	if err != nil {
		return nil, err
	}

	r = &DownPayResult{}
	err = types.Map2Struct(r, result, "json")
	return
}

//UpChannelPay 上游扣款
func UpChannelPay(params *UpPay) (r *UpPayResult, err error) {
	if !conf.KeepAccount {
		return &UpPayResult{Result: "success", Msg: "success"}, nil
	}
	downDrawnAmount, _ := decimal.NewFromFloat(params.DownSellAmount).Sub(decimal.NewFromFloat(params.DownFeeAmount)).Float64()
	downRealAmount, _ := decimal.NewFromFloat(params.DownSellAmount).Sub(decimal.NewFromFloat(params.DownCommissionAmount)).Sub(decimal.NewFromFloat(params.DownFeeAmount)).Add(decimal.NewFromFloat(params.DownServiceAmount)).Float64()
	upRealAmount, _ := decimal.NewFromFloat(params.UpCostAmount).Sub(decimal.NewFromFloat(params.UpCommissionAmount)).Sub(decimal.NewFromFloat(params.UpServiceAmount)).Float64()
	data := &normal.UpPay{
		OrderSource:       params.OrderSource,
		DownChannelNo:     params.DownChannelNo,
		UpChannelNo:       params.UpChannelNo,
		TradeOrderNo:      params.TradeOrderNo,
		TradeDeliveryNo:   params.TradeDeliveryNo,
		ExtOrderNo:        params.ExtOrderNo,
		RechargeAccountNo: params.RechargeAccountNo,
		BillType:          params.BillType,
		BusinessType:      params.BusinessType,
		CarrierNo:         params.CarrierNo,
		ProvinceNo:        params.ProvinceNo,
		CityNo:            params.CityNo,
		DownOrderUnit:     params.DownOrderUnit,
		DownOrderFace:     params.DownOrderFace,
		DownDrawUnit:      params.DownDrawUnit,
		DownDrawFace:      params.DownDrawFace,
		DownDrawAmount:    downDrawnAmount,
		DownRealAmount:    downRealAmount,
		UpDrawUnit:        params.UpDrawUnit,
		UpDrawFace:        params.UpDrawFace,
		UpDrawAmount:      params.UpCostAmount,
		UpRealAmount:      upRealAmount,
		OrderTime:         params.OrderTime,
		ServiceFee:        0,
		Memo:              params.Memo,
	}

	billing, err := normal.NewBilling()
	if err != nil {
		return nil, err
	}

	result, err := billing.UpChannelPay(data)
	if err != nil {
		return nil, err
	}

	r = &UpPayResult{}
	err = types.Map2Struct(r, result, "json")
	return
}

//SupUpChannelPay Sup上游扣款
func SupUpChannelPay(params *SupUpPay) (r *UpPayResult, err error) {
	if !conf.KeepAccount {
		return &UpPayResult{Result: "success", Msg: "success"}, nil
	}
	data := &sup.SupUpPay{
		UpChannelNo:     params.UpChannelNo,
		DownChannelNo:   params.DownChannelNo,
		TradeOrderNo:    params.TradeOrderNo,
		TradeDeliveryNo: params.TradeDeliveryNo,
		BillType:        params.BillType,
		BusinessType:    params.BusinessType,
		CarrierNo:       params.CarrierNo,
		ProvinceNo:      params.ProvinceNo,
		CityNo:          params.CityNo,
		OrderUnit:       params.OrderUnit,
		OrderFace:       params.OrderFace,
		OrderAmount:     params.OrderAmount,
		UpDrawCount:     params.UpDrawCount,
		UpDrawUnit:      params.UpDrawUnit,
		UpDrawFace:      params.UpDrawFace,
		UpDrawAmount:    params.UpCostAmount,
		OrderTime:       params.OrderTime,
		ChangeTime:      params.ChangeTime,
		Memo:            params.Memo,
	}

	billing, err := sup.NewBilling()
	if err != nil {
		return nil, err
	}

	result, err := billing.UpChannelPay(data)
	if err != nil {
		return nil, err
	}

	r = &UpPayResult{}
	err = types.Map2Struct(r, result, "json")
	return
}

//DownChannelRefund 下游渠道退款
func DownChannelRefund(params *DownRefund) (r *DownRefundResult, err error) {
	if !conf.KeepAccount {
		return &DownRefundResult{Result: "success", Msg: "success"}, nil
	}
	refundAmount, _ := decimal.NewFromFloat(params.DownRefundAmount).Sub(decimal.NewFromFloat(params.DownRefundFeeAmount)).Float64()
	realRefund, _ := decimal.NewFromFloat(params.DownRefundAmount).Sub(decimal.NewFromFloat(params.DownRefundCommissionAmount)).Add(decimal.NewFromFloat(params.DownRefundServiceAmount)).Sub(decimal.NewFromFloat(params.DownRefundFeeAmount)).Float64()
	data := &normal.DownRefund{
		OrderSource:   params.OrderSource,
		DownChannelNo: params.DownChannelNo,
		TradeOrderNo:  params.TradeOrderNo,
		TradeRefundNo: params.TradeRefundNo,
		RefundUnit:    params.RefundUnit,
		RefundFace:    params.RefundFace,
		RefundAmount:  refundAmount, //@
		RealRefund:    realRefund,
		OrderDate:     params.OrderDate,
		ServiceFee:    params.DownRefundFeeAmount,
		Memo:          params.Memo,
	}

	billing, err := normal.NewBilling()
	if err != nil {
		return nil, err
	}

	result, err := billing.DownChannelRefund(data)
	if err != nil {
		return nil, err
	}

	r = &DownRefundResult{}
	err = types.Map2Struct(r, result, "json")
	return
}

//SupDownChannelRefund sup下游渠道退款
func SupDownChannelRefund(params *SupDownRefund) (r *DownRefundResult, err error) {
	if !conf.KeepAccount {
		return &DownRefundResult{Result: "success", Msg: "success"}, nil
	}
	refundAmount, _ := decimal.NewFromFloat(params.DownRefundAmount).Sub(decimal.NewFromFloat(params.DownRefundFeeAmount)).Float64()
	data := &sup.DownRefund{
		DownChannelNo: params.DownChannelNo,
		TradeOderNo:   params.TradeOrderNo,
		TradeRefundNo: params.TradeRefundNo,
		RefundFace:    params.RefundFace,
		RefundAmount:  refundAmount, //@
		OrderTime:     params.OrderTime,
		ChangeTime:    params.ChangeTime,
		Memo:          params.Memo,
	}

	billing, err := sup.NewBilling()
	if err != nil {
		return nil, err
	}
	result, err := billing.DownChannelRefund(data)
	if err != nil {
		return nil, err
	}

	r = &DownRefundResult{}
	err = types.Map2Struct(r, result, "json")
	return
}

//UpChannelRefund 上游渠道退款
func UpChannelRefund(params *UpRefund) (r *UpRefundResult, err error) {
	if !conf.KeepAccount {
		return &UpRefundResult{Result: "success", Msg: "success"}, nil
	}
	upRefundRealAmount, _ := decimal.NewFromFloat(params.UpRefundAmount).Sub(decimal.NewFromFloat(params.UpRefundServiceAmount)).Sub(decimal.NewFromFloat(params.UpRefundCommissionAmount)).Float64()
	data := &normal.UpRefund{
		OrderSource:        params.OrderSource,
		DownChannelNo:      params.DownChannelNo,
		UpChannelNo:        params.UpChannelNo,
		TradeOrderNo:       params.TradeOrderNo,
		TradeDeliveryNo:    params.TradeDeliveryNo,
		TradeRefundNo:      params.TradeRefundNo,
		BillType:           params.BillType,
		BusinessType:       params.BusinessType,
		CarrierNo:          params.CarrierNo,
		ProvinceNo:         params.ProvinceNo,
		UpRefundUnit:       params.UpRefundUnit,
		UpRefundFace:       params.UpRefundFace,
		UpRefundAmount:     params.UpRefundAmount,
		UpRefundRealAmount: upRefundRealAmount,
		OrderTime:          params.OrderTime,
		ServiceFee:         0,
		Memo:               params.Memo,
	}

	billing, err := normal.NewBilling()
	if err != nil {
		return nil, err
	}

	result, err := billing.UpChannelRefund(data)
	if err != nil {
		return nil, err
	}

	r = &UpRefundResult{}
	err = types.Map2Struct(r, result, "json")
	return
}

//SupUpChannelRefund sup上游渠道退款
func SupUpChannelRefund(params *SupUpRefund) (r *UpRefundResult, err error) {
	if !conf.KeepAccount {
		return &UpRefundResult{Result: "success", Msg: "success"}, nil
	}
	upRefundAmount, _ := decimal.NewFromFloat(params.UpRefundAmount).Sub(decimal.NewFromFloat(params.UpRefundFeeAmount)).Float64()
	data := &sup.UpRefund{
		UpChannelNo:     params.UpChannelNo,
		DownChannelNo:   params.DownChannelNo,
		TradeOrderNo:    params.TradeOrderNo,
		TradeDeliveryNo: params.TradeDeliveryNo,
		TradeRefundNo:   params.TradeRefundNo,
		BillType:        params.BillType,
		BusinessType:    params.BusinessType,
		UpRefundCount:   params.UpRefundCount,
		UpRefundUnit:    params.UpRefundUnit,
		UpRefundFace:    params.UpRefundFace,
		UpRefundAmount:  upRefundAmount, //
		OrderTime:       params.OrderTime,
		ChangeTime:      params.ChangeTime,
		Memo:            params.Memo,
	}
	billing, err := sup.NewBilling()
	if err != nil {
		return nil, err
	}

	result, err := billing.UpChannelRefund(data)
	if err != nil {
		return nil, err
	}

	r = &UpRefundResult{}
	err = types.Map2Struct(r, result, "json")
	return
}

//GetSupZeroBalance 获取记账系统零点余额
//channelNo 渠道编号 rptDate yyyy-mm-dd
func GetSupZeroBalance(channelNo, rptDate string) (list *ZeroBalance, err error) {

	billing, err := sup.NewBilling()
	if err != nil {
		return nil, err
	}
	data, err := billing.GetReportZeroBalance(channelNo, rptDate)
	if err != nil {
		return nil, err
	}

	list = &ZeroBalance{}

	if err = json.Unmarshal([]byte(data), list); err != nil {
		return nil, fmt.Errorf("json.Unmarshal,err:%+v,data:%s", err, data)
	}

	return list, err
}

// AddAmount 加款
//i-->nil/db.IDBTrans/db.IDB
func AddAmount(i interface{}, ident, group, eid, tradeNo, memo string, amount float64) (*account.RecordResult, error) {
	return nil, fmt.Errorf("记账系统不支持加款")
}

// DrawingAmount 提款
//i-->nil/db.IDBTrans/db.IDB
func DrawingAmount(i interface{}, ident, group, eid, tradeNo, memo string, amount float64) (*account.RecordResult, error) {
	return nil, fmt.Errorf("记账系统不支持提款")
}

// ReverseAddAmount 红冲加款
//i-->nil/db.IDBTrans/db.IDB
func ReverseAddAmount(i interface{}, ident, group, eid, tradeNo, extNo, memo string) (*account.RecordResult, error) {
	return nil, fmt.Errorf("记账系统不支持红冲加款")
}

// ReverseDrawingAmount 红冲提款
//i-->nil/db.IDBTrans/db.IDB
func ReverseDrawingAmount(i interface{}, ident, group, eid, tradeNo, extNo, memo string) (*account.RecordResult, error) {
	return nil, fmt.Errorf("记账系统不支持红冲提款")
}

// TradeFlatAmount 交易平账
//i-->nil/db.IDBTrans/db.IDB
func TradeFlatAmount(i interface{}, ident, group, eid, tradeNo, memo string, tradeType ttypes.TradeType, amount float64) (*account.RecordResult, error) {
	return nil, fmt.Errorf("记账系统不支持交易平账")
}

// BalanceFlatAmount 余额平账
//i-->nil/db.IDBTrans/db.IDB
func BalanceFlatAmount(i interface{}, ident, group, eid, tradeNo, memo string, tradeType ttypes.TradeType, amount float64) (*account.RecordResult, error) {
	return nil, fmt.Errorf("记账系统不支持余额平账")
}

// SetCreditAmount 设置授信金额
//i-->nil/db.IDBTrans/db.IDB
func SetCreditAmount(i interface{}, ident, group, eid string, credit float64) (*account.AccountResult, error) {
	return nil, fmt.Errorf("记账系统不支持设置授信金额")
}
